package com.jay.studyproject.interview;

public class Demo2{
    /**
     *一、对于Context，你了解多少?
     * 1、Context 概念
     * Context是个抽象类，通过类的结构可以看到：Activity、Service、Application都是Context的子类；
     * 从Android系统的角度来理解：Context是一个场景，描述的是一个应用程序环境的信息，即上下文，代表与操作系统的交互的一种过程。
     * 从程序的角度上来理解：Context是个抽象类，而Activity、Service、Application等都是该类的一个实现。
     * 应用在三种情况下会创建Context对象（即通常说的context）：
     * 1> 创建Application 对象时，即第一次启动app时。 整个App共一个Application对象，所以也只有一个Application 的Context，Application销毁，它也销毁；
     * 2> 创建Activity对象时。Activity销毁，它也销毁;
     * 3> 创建Service对象时。Service销毁，它也销毁。
     * 由此可以得到应用程序App可以创建的Context（Activity和Service没启动就不会创建）个数公式一般为：
     * 总Context实例个数 = Service个数 + Activity个数 + 1（Application对应的Context对象）
     * 2、源码中的Context
     * Context提供了关于应用环境全局信息的接口。它是一个抽象类，它的执行被Android系统所提供。它允许获取以应用为特征的资源和类型，
     * 是一个统领一些资源（应用程序环境变量等）的上下文。就是说，它描述一个应用程序环境的信息（即上下文）；是一个抽象类，
     * Android提供了该抽象类的具体实现类；通过它我们可以获取应用程序的资源和类（包括应用级别操作，如启动Activity，发广播，接受Intent等）。
     * 既然上面Context是一个抽象类，那么肯定有他的实现类咯，我们在Context的源码中通过IDE可以查看到他的子类最终可以得到如下关系图：
     *
     *
     * 3、Context作用域
     * 虽然Context神通广大，但并不是随便拿到一个Context实例就可以为所欲为，它的使用还是有一些规则限制的。由于Context的具体实例是由ContextImpl类去实现的，
     * 因此在绝大多数场景下，Activity、Service和Application这三种类型的Context都是可以通用的。不过有几种场景比较特殊，比如启动Activity，还有弹出Dialog。
     * 出于安全原因的考虑，Android是不允许Activity或Dialog凭空出现的，一个Activity的启动必须要建立在另一个Activity的基础之上，也就是以此形成的返回栈。
     * 而Dialog则必须在一个Activity上面弹出（除非是System Alert类型的Dialog），因此在这种场景下，我们只能使用Activity类型的Context，否则将会出错。
     *
     * 上图中Application和Service所不推荐的两种使用情况：
     * 1：如果我们用ApplicationContext去启动一个LaunchMode为standard的Activity的时候会报错android.util.AndroidRuntimeException:
     * Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
     * 这是因为非Activity类型的Context并没有所谓的任务栈，所以待启动的Activity就找不到栈了。解决这个问题的方法就是为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位，
     * 这样启动的时候就为它创建一个新的任务栈，而此时Activity是以singleTask模式启动的。所有这种用Application启动Activity的方式不推荐使用，Service同Application。
     *
     * 2：在Application和Service中去layout inflate也是合法的，但是会使用系统默认的主题样式，如果你自定义了某些样式可能不会被使用。所以这种方式也不推荐使用。
     * 一句话总结：凡是跟UI相关的，都应该使用Activity做为Context来处理；其他的一些操作，Service,Activity,Application等实例都可以，当然了，注意Context引用的持有，防止内存泄漏。
     * 4 Context数量
     * Context一共有Application、Activity和Service三种类型，因此一个应用程序中Context数量的计算公式就可以这样写：
     * Context数量 = Activity数量 + Service数量 + 1
     * 5正确使用Context
     * 一般Context造成的内存泄漏，几乎都是当Context销毁的时候，却因为被引用导致销毁失败，而Application的Context对象可以理解为随着进程存在的，所以我们总结出使用Context的正确姿势：
     * 1：当Application的Context能搞定的情况下，并且生命周期长的对象，优先使用Application的Context。
     * 2：不要让生命周期长于Activity的对象持有到Activity的引用。
     * 3：尽量不要在Activity中使用非静态内部类，因为非静态内部类会隐式持有外部类实例的引用，如果使用静态内部类，将外部实例引用作为弱引用持有。
     * 二、Application 和 Activity 的 Context 对象的区别
     * 1）Application Context是伴随应用生命周期；不可以showDialog, startActivity, LayoutInflation
     * 可以startService\BindService\sendBroadcast\registerBroadcast\load Resource values
     * 2）Activity Context指生命周期只与当前Activity有关，而Activity Context这些操作都可以，即凡是跟UI相关的，都得用Activity做为Context来处理。
     * 一个应用Context的数量=Activity数量+Service数量+1（Application数量）
     *
     *
     *一、ContentProvider
     * 在应用之间提供数据共享，非常适合进程间的通信。它比AIDL操作起来更方便，所有ContentProvicer也是一个比较好的跨进程通信的方式。
     * *初始化时间
     * *多线程，多进程
     * *存放Android中的数据，以安全的形式进行封装
     * *Android为什么要设计Content Provider这个组件？
     * 答：(1)可以对数据进行封装，从而提供一个统一的接口
     * (2)提供了跨进程数据共享的方式
     * 二、简单介绍下ContentProvider是如何实现数据共享的？
     * 三、说说ContentProvider、ContentResolver、ContentObserver 之间的关系？
     * ContentProvider实现各个应用程序间数据共享，用来提供内容给别的应用操作。如联系人应用中就使用了ContentProvider，可以在自己应用中读取和修改联系人信息，
     * 不过需要获取相应的权限。它也只是一个中间件，真正的数据源是文件或SQLite等。
     * ContentResolver内容解析者，用于获取内容提供者提供的数据，通过ContentResolver.notifyChange(uri)发出消息
     * ContentObserver内容监听者，可以监听数据的改变状态，观察特定Uri引起的数据库变化，继而做一些相应的处理，类似于数据库中的触发器，当ContentObserver所观察的Uri发生变化时，便会触发它。
     *
     *
     *
     *
     * 一、BroadcastReceiver
     * 在Android中，Broadcast是一种广泛运用的在应用程序之间传输信息的机制，Android中我们要发送的广播内容是一个Intent,这个Intent中可以携带我们要传送的数据。
     * *原理
     * 观察者模式
     * *注册
     * (1)静态注册：注册完成就一直运行(Mainifest.xml配置)
     * (2)动态注册:：跟随activity的生命周期(代码设置)
     * *广播类型
     * (1) 有序广播
     * (2) 系统广播
     * (3) 普通广播
     * (4) 本地广播
     * *广播的使用场景
     * (1) 同一个app具有多个进程的不用组件之间的消息通信
     * (2) 不同app之间的组件之间消息通信
     * *内部实现机制
     * (1) 自定义广播接收者BroadcastReceiver,并复写onRecvice()方法；
     * (2) 通过Binder机制向AMS(Activity Manager Service)进行注册；
     * (3) 广播发送者通过Binder机制向AMS发送广播;
     * (4) AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中
     * (5) 消息循环执行拿到此广播，回调BroadcastReceiver中的onReceiver()方法
     *
     * 二、BroadcastReceiver注册
     * a) 动态注册：存活周期是在Context.registerReceiver和Context.unregisterReceiver之间，BroadcastReceiver每次收到广播都是使用注册传入的对象处理的。
     * b) 静态注册：进程在的情况下，receiver会正常收到广播，调用onReceive方法；生命周期只存活在onReceive函数中，此方法结束，BroadcastReceiver就销毁了。onReceive()只有十几秒存活时间，
     * 在onReceive()内操作超过10S，就会报ANR。
     * 进程不存在的情况，广播相应的进程会被拉活，Application.onCreate会被调用，再调用onReceive。
     * 三、BroadcastReceiver 与LocalBroadcastReceiver 有什么区别？
     * BroadcastReceiver是针对应用间、应用与系统间、应用内部进行通信的一种方式
     * LocalBroadcastReceiver仅在自己的应用内发送接收广播，也就是只有自己的应用能收到，数据更加安全广播只在这个程序里，而且效率更高。
     * BroadcastReceiver 使用
     * 1.制作intent（可以携带参数）
     * 2.使用sendBroadcast()传入intent;
     * 3.制作广播接收器类继承BroadcastReceiver重写onReceive方法（或者可以匿名内部类啥的）
     * 4.在java中（动态注册）或者直接在Manifest中注册广播接收器（静态注册）使用registerReceiver()传入接收器和intentFilter
     * 5.取消注册可以在OnDestroy()函数中，unregisterReceiver()传入接收器
     * LocalBroadcastReceiver 使用
     * 1.LocalBroadcastReceiver不能静态注册，只能采用动态注册的方式。
     * 在发送和注册的时候采用，LocalBroadcastManager的sendBroadcast方法和registerReceiver方法
     * 四、 广播的分类
     * 1）普通广播：完全异步的，可以在同一时刻（逻辑上）被所有接收者接收到，消息传递的效率比较高，并且无法中断广播的传播。
     * 2）有序广播：发送有序广播后，广播接收者将按预先声明的优先级依次接收Broadcast。优先级高的优先接收到广播，而在其onReceiver()执行过程中，广播不会传播到下一个接收者，此时当前的广播接收者可以abortBroadcast()来终止广播继续向下传播，也可以将intent中的数据进行修改设置，然后将其传播到下一个广播接收者。 sendOrderedBroadcast(intent, null);//发送有序广播
     * 3）本地广播：仅在自己的应用内发送接收广播，也就是只有自己的应用能收到，数据更加安全，效率更高，但只能采用动态注册的方式；
     * 4）粘性广播：sendStickyBroadcast()来发送该类型的广播信息，这种的广播的最大特点是，当粘性广播发送后，最后的一个粘性广播会滞留在操作系统中。如果在粘性广播发送后的一段时间里，如果有新的符合广播的动态注册的广播接收者注册，将会收到这个广播消息，虽然这个广播是在广播接收者注册之前发送的，另外一点，对于静态注册的广播接收者来说，这个等同于普通广播。
     * 五、广播使用的方式和场景
     * 1）App全局监听：在AndroidManifest中静态注册的广播接收器，一般我们在收到该消息后，需要做一些相应的动作，而这些动作与当前App的组件，比如Activity或者Service的是否运行无关，比如我们在集成第三方Push SDK时，一般都会添加一个静态注册的BroadcastReceiver来监听Push消息，当有Push消息过来时，会在后台做一些网络请求或者发送通知等等。
     * 2）组件局部监听：这种主要是在Activity或者Service中使用registerReceiver()动态注册的广播接收器，因为当我们收到一些特定的消息，比如网络连接发生变化时，我们可能需要在当前Activity页面给用户一些UI上的提示，或者将Service中的网络请求任务暂停。所以这种动态注册的广播接收器适合特定组件的特定消息处理。
     * 六、在manifest 和代码中如何注册和使用BroadcastReceiver?
     * 1）mainfest中注册:静态注册的广播接收者就是一个常驻在系统中的全局监听器，也就是说如果你应用中配置了一个静态的BroadcastReceiver，而且你安装了应用而无论应用是否处于运行状态，广播接收者都是已经常驻在系统中了。
     * <receiver android:name=".MyBroadcastReceiver">
     * <intent-filter>
     * <action android:name="com.smilexie.test.intent.mybroadcastreceiver"/>
     * </intent-filter>
     * </receiver>
     * 2) 动态注册:动态注册的广播接收者只有执行了registerReceiver(receiver, filter)才会开始监听广播消息，并对广播消息作为相应的处理。
     * IntentFilter fiter = new IntentFilter("com.smilexie.test.intent.mybroadcastreceiver");
     * MyBroadcastReceiver receiver = new MyBroadcastReceiver();
     * registerReceiver(receiver, filter);
     * //撤销广播接受者的动态注册
     * unregisterReceiver(receiver);
     * 七、广播发送和接收的原理了解吗 ？（Binder 机制、AMS）
     *
     *
     *一、生命周期
     * Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。(不能做耗时操作)
     * *生命周期
     * (1) bindService
     * 1. 创建BindService服务端，继承自Service并在类中，创建一个实现IBinder接口的实例对象并提供公共方法给客户端调用
     * 2. 从onBind()回调方法返回此Binder实例
     * 3. 在客户端中，从onServiceConnected()回调方法接收Binder,并使用提供的方法调用绑定服务。
     * (2) startService
     * 1. 定义一个类继承Service
     * 2. 在Mainifest.xml文件中配置该Service
     * 3. 使用Context的startService(Intent)方法启动该Service
     * 4. 不再使用时，调用stopService(Intent)方法停止该服务
     * *分类
     * (1) 按地点分：本地服务；远程服务
     * (2) 运行类型分：前台服务；后台服务
     * (3) 使用方式：start;bind;混合类型
     *
     * 二、startService和bindService的区别
     * (1)生命周期上的区别
     * startService启动服务：Service会经历onCreate()------->onStartCommand()。当执行stopService时，直接调用onDestroy方法。调用者如果没有stopService，Service会一直在后台运行，下次调用者再次启动仍然可以stopService。
     * 多次调用startService，该Service只能被创建一次，即该Service的onCreate()只会被调用一次。但是每次调用startService，onStartCommand()都会被调用。
     * bindService启动服务：Service会经历onCreate()----->onBind()。这个时候调用者和Service捆绑在一起。调用者调用unbindService方法或者调用者Context不存在了（如Activity被finish（销毁）了），Service就会调用onUnbind()------>onDestroy()。
     * 第一次执行bindService时，onCreate()和onBind()会被调用，但是多次执行bindService时，onCreate()和onBind()方法并不会被多次调用(下图中的日志空白情况)，即并不会多次创建服务和绑定服务。
     * (2)只有bindService启动服务才能获取绑定后的Service的方法，所以说具体的Service对象必须首先实现Binder（中间人）对象。
     * (3)startService在Activity所在进程被终结后，服务依然在运行。该服务是独立的进程，会占用一定资源—>缺点
     * bindService方便很多。缺点是主进程被终结后，服务便会终止
     *
     * 三、谈一谈Service 的生命周期？
     * service 的生命周期涉及到六大方法
     * ① onCreate()：如果 service 没被创建过，调用startService()后会执行 onCreate()回调；如果 service已处于运行中，调用 startService()不会执行 onCreate()方法。也就是说，onCreate()只会在第一次创建 service时候调用，多次执行 startService()不会重复调用onCreate()，此方法适合完成一些初始化工作；
     * ② onStartComand()：服务启动时调用，此方法适合完成一些数据加载工作，比如会在此处创建一个线程用于下载数据或播放音乐；
     * ③ onBind()：服务被绑定时调用；
     * ④ onUnBind()：服务被解绑时调用；
     * ⑤ onDestroy()：服务停止时调用；
     *
     * 四、谈一谈startService和bindService的区别，生命周期以及使用场景？
     * a) onBind方式绑定的：onCreate->onBind->onUnBind->onDestory（不管调用bindService几次，onCreate只会调用一次，onStart不会被调用，建立连接后，service会一直运行，直到调用unBindService或是之前调用的bindService的Context不存在了，系统会自动停止Service,对应的onDestory会被调用）
     * b) startService启动的：onCreate->onStartCommand->onDestory(start多次，onCreate只会被调用一次，onStart会调用多次，该service会在后台运行，直至被调用stopService或是stopSelf)
     * c) 又被启动又被绑定的服务，不管如何调用onCreate()只被调用一次，startService调用多少次，onStart就会被调用多少次，而unbindService不会停止服务，必须调用stopService或是stopSelf来停止服务。必须unbindService和stopService(stopSelf）同时都调用了才会停止服务。
     * 使用场景
     * 如果想要启动一个后台服务长期进行某项任务，那么使用startService
     * 如果只是短暂的使用，那么使用bindService。
     * 如果想启动一个后台服务长期进行任务，且这个过程中需要与调用者进行交互，那么可以两者同时使用，或者使用startService + BoardCast/ EventBus 等方法。
     * 对于既使用startService，又使用bindService的情况，结束服务时需要注意的事项：Service的终止，需要unbindService和stopService都调用才行；
     *
     * 五、是否使用过IntentService，作用是什么
     * 如果有一个任务，可以分成很多个子任务，需要按照顺序来完成，如果需要放到一个服务中完成，那么使用IntentService是最好的选择。
     * 一般我们所使用的Service是运行在主线程当中的，所以在service里面编写耗时的操作代码，则会卡主线程会ANR。为了解决这样的问题，谷歌引入了IntentService.
     * IntentService的优点：
     * 它创建一个独立的工作线程来处理所有一个一个intent。
     * 创建了一个工作队列，来逐个发送intent给onHandleIntent()
     * 不需要主动调用stopSelf()来结束服务，因为源码里面自己实现了自动关闭。
     * 默认实现了onBind()返回的null。
     * 默认实现的onStartCommand()的目的是将intent插入到工作队列。
     * 总结：使用IntentService的好处有哪些。首先，省去了手动开线程的麻烦；第二，不用手动停止service；第三，由于设计了工作队列，可以启动多次---startService(),但是只有一个service实例和一个工作线程。一个一个熟悉怒执行。
     * 六、如何保证Service 不被杀死 ？
     * ① onStartCommand 方式中，返回 START_STICKY 或则 START_REDELIVER_INTENT             	START_STICKY：如果返回 START_STICKY，表示Service 运行的进程被 Android 系统强制杀掉之后，Android 系统会将该 Service 依然设置为started 状态（即运行状态），但是不再保存onStartCommand 方法传入的 intent 对象
     * START_NOT_STICKY：如果返回 START_NOT_STICKY，表示当 Service 运行的进程被 Android 系统强制杀掉之后，不会重新创建该 Service
     * START_REDELIVER_INTENT：如果返回START_REDELIVER_INTENT，其返回情况与START_STICKY 类似，但不同的是系统会保留最后一次传入 onStartCommand 方法中的 Intent 再次保留下来并再次传入到重新创建后的 Service 的onStartCommand 方法中
     * ② 提高Service 的优先级 在 AndroidManifest.xml 文件中对于 intent-filter 可以通过 android:priority = "1000"这个属性设置最高优先级，1000 是最高值，如果数字越小则优先级越低，同时适用于广播；
     * ③ 在onDestroy 方法里重启 Service 当 service 走到onDestroy()时，发送一个自定义广播，当收到广播时，重新启动 service；
     * ④ 提升Service 进程的优先级 进程优先级由高到低：前台进程 一 可视进程 一 服务进程 一 后台进程 一 空进程 可以使用 startForeground 将 service 放到前台状态，这样低内存时，被杀死的概率会低一些；
     * ⑤ 系统广播监听Service 状态
     * ⑥ 将APK 安装到/system/app，变身为系统级应用
     * ·注意：以上机制都不能百分百保证Service 不被杀死，除非做到
     * 系统白名单，与系统同生共死
     * 七、了解ActivityManagerService 吗？发挥什么作用
     * ActivityManagerService 是 Android 中最核心的服务，主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作，其职责与操作系统中的进程管理和调度模块类似；
     * 八、IntentService的应用场景和使用方式？
     * 1： IntenteService是 Service的 子类，用来处理异步请求，客户端通过 startService(intent) 将请求传递给 intentService, 其中 IntentService在onCreate() 函数中，通过HandlerThread 单独开启一个线程来处理所有的 intent请求对象，所对应的 任务，这样可以避免阻塞主线程，在执行完一个 inentServcie请求对象之后，如果没有新的 Intent请求到达，则自动停止 Service, 否则就执行下一个 intent 请求对应的任务
     * 2 ：IntenteService在处理事务时，还是采用Handler方式，创建一个名叫 ServiceHandler 的内部handler , 并绑定到 HandlerThread所对应的 子线程，ServiceHandler 吧处理一个Intent所对应的事务都封装在 onHandleIntent的虚函数中，因此我们需要实现 onHandleIntenth函数，在实现的函数里面 根据不同 intent 处理不同事务或者任务就可以了
     * 使用 IntentServcie的步骤
     * ● 写构造函数
     * ● 实现 虚函数onHandleIntent()
     * ● 启动 IntentServcie : startService(context, intentServcie.class) ; (注意 intentService默认实现了onBind() 函数，但是onBind() 函数返回值是 null )
     * ● 另外，不建议通过 bindService() 启动 IntentService。IntentService 源码中的 onBind() 默认返回 null；不适合 bindService() 启动服务，如果你执意要 bindService() 来启动 IntentService，可能因为你想通过 Binder 或 Messenger 使得 IntentService 和 Activity 可以通信，这样那么 onHandleIntent() 不会被回调，相当于在你使用 Service 而不是 IntentService。
     * intentService 停止：
     * onHandleIntent （ ） 里面的任务如果执行完毕，那么service会自动停止，不需要手动 stop, 如果任务没有执行完毕，service不会停止，
     * 而 onHandleIntent() 里面的任务 ，就是通过 startService(context, intentServcie.class)传递的，多次启动会将任务依次放到 onHandleIntent () 中，并且 intentService 只会启动一次 （即多次启动，onCreate（）运行一次，但是会运行多次 onStartCommand() 函数）
     * 使用场景
     * 在Android开发中，我们或许会碰到这么一种业务需求，一项任务分成几个子任务，子任务按顺序先后执行，子任务全部执行完后，这项任务才算成功。
     * ● 那么，利用几个子线程顺序执行是可以达到这个目的的，但是每个线程必须去手动控制，而且得在一个子线程执行完后，再开启另一个子线程。
     * ● 或者，全部放到一个线程中让其顺序执行。这样都可以做到，
     * ● 但是，如果这是一个后台任务，就得放到Service里面，由于Service和Activity是同级的，所以，要执行耗时任务，就得在Service里面开子线程来执行。那么，有没有一种简单的方法来处理这个过程呢，答案就是IntentService。
     * 九、 service和Thread的区别
     */
}
